package main

import (
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	modbus "gitee.com/barryzxy/gomodbus"
)

func main() {
	fmt.Println("=== 网关协议完整演示（服务端+客户端）===")

	// 启动服务端
	server := startGatewayServer()
	defer server.Stop()

	// 等待服务端启动
	time.Sleep(100 * time.Millisecond)

	// 启动客户端演示
	go clientDemo()

	// 等待退出信号
	fmt.Println("\n按 Ctrl+C 退出...")
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
	<-sigChan

	fmt.Println("\n=== 演示结束 ===")
}

func startGatewayServer() *modbus.TCPServer {
	fmt.Println("\n🖥️  启动网关协议服务端...")

	// 创建TCP服务器
	server := modbus.NewTCPServer()

	// 创建变送器节点 (Unit ID = 5)
	transmitterNode := modbus.NewNodeRegister(5, 0, 0, 0, 0, 0, 0, 0, 10)
	transmitterNode.InitGatewayDataStore(1000) // 最多存储1000条记录

	// 创建网关节点 (Unit ID = 65)
	gatewayNode := modbus.NewNodeRegister(65, 0, 0, 0, 0, 0, 0, 0, 10)
	gatewayNode.InitGatewayDataStore(1000)

	// 添加模拟数据到变送器
	setupSimulatedData(transmitterNode)

	// 添加节点到服务器
	server.AddNodes(transmitterNode, gatewayNode)

	// 启动服务器
	go func() {
		if err := server.ListenAndServe(":5020"); err != nil {
			log.Printf("服务器启动失败: %v", err)
		}
	}()

	fmt.Println("✓ 网关协议服务端启动完成 (端口: 5020)")
	return server
}

func setupSimulatedData(node *modbus.NodeRegister) {
	store := node.GetGatewayDataStore()
	if store == nil {
		return
	}

	// 添加历史数据记录
	baseTime := uint32(time.Now().Unix() - 3600) // 1小时前开始
	for i := 0; i < 50; i++ {
		record := &modbus.DataRecord{
			Pressure:         float32(20.0 + float64(i)*0.1),
			PressureUnit:     modbus.PressureUnitKPa,
			BatteryLevel:     uint8(90 + i%10),
			ConnectionStatus: 1,
			SignalLevel:      uint8(3 + i%3),
			Timestamp:        baseTime + uint32(i*60), // 每分钟一条记录
		}
		store.AddRecord(record)
	}

	// 设置当前数据
	currentData := &modbus.DataRecord{
		Pressure:         25.8,
		PressureUnit:     modbus.PressureUnitKPa,
		BatteryLevel:     88,
		ConnectionStatus: 1,
		SignalLevel:      4,
		Timestamp:        uint32(time.Now().Unix()),
	}
	store.SetCurrentData(currentData)

	// 设置初始参数
	store.SetSubDevParam(modbus.SubDevParamPressureUnit, modbus.PressureUnitKPa)
	store.SetSubDevParam(modbus.SubDevParamDataReportInterval, 60)
	store.SetGatewayParam(modbus.GatewayParamRS485Baudrate, 9600)
	store.SetGatewayParam(modbus.GatewayParamTime, uint32(time.Now().Unix()))

	fmt.Println("✓ 模拟数据初始化完成")
}

func clientDemo() {
	time.Sleep(200 * time.Millisecond) // 等待服务端完全启动

	fmt.Println("\n📱 启动网关协议客户端演示...")

	// 创建客户端
	provider := modbus.NewTCPClientProvider("127.0.0.1:5020",
		modbus.WithTCPTimeout(3*time.Second),
		modbus.WithEnableLogger())
	client := modbus.NewClient(provider)

	// 连接到服务器
	if err := client.Connect(); err != nil {
		log.Printf("客户端连接失败: %v", err)
		return
	}
	defer client.Close()

	fmt.Println("✓ 客户端连接成功")

	// 演示完整的网关协议功能
	demonstrateFullGatewayProtocol(client)
}

func demonstrateFullGatewayProtocol(client modbus.Client) {
	fmt.Println("\n=== 网关协议功能演示 ===")

	// 1. 读取变送器当前数据
	fmt.Println("\n1. 读取变送器当前数据 (功能码 0x51):")
	currentData, err := client.GatewayReadCurrentData(5)
	if err != nil {
		fmt.Printf("   ❌ 错误: %v\n", err)
	} else {
		fmt.Printf("   ✅ 成功读取当前数据:\n")
		fmt.Printf("      压力: %s\n", currentData.GetPressureString())
		fmt.Printf("      电池电量: %d%%\n", currentData.BatteryLevel)
		fmt.Printf("      连接状态: %s\n", modbus.GetConnectionStatusName(currentData.ConnectionStatus))
		fmt.Printf("      信号强度: %s\n", currentData.GetSignalStrengthDescription())
		fmt.Printf("      采集时间: %s\n", currentData.GetTimeString())
	}

	// 2. 数据对齐
	fmt.Println("\n2. 数据对齐 (功能码 0x50 - 对齐模式):")
	alignedTimestamp, err := client.GatewayReadDataRecordsAlign(5, 0)
	if err != nil {
		fmt.Printf("   ❌ 错误: %v\n", err)
	} else {
		fmt.Printf("   ✅ 成功获取对齐时间戳: %d\n", alignedTimestamp)
		fmt.Printf("      对应时间: %s\n", time.Unix(int64(alignedTimestamp), 0).Format("2006-01-02 15:04:05"))
	}

	// 3. 批量读取历史数据
	fmt.Println("\n3. 批量读取历史数据 (功能码 0x50 - 批量模式):")
	if alignedTimestamp > 0 {
		records, err := client.GatewayReadDataRecords(5, alignedTimestamp-1800) // 30分钟前的数据
		if err != nil {
			fmt.Printf("   ❌ 错误: %v\n", err)
		} else {
			fmt.Printf("   ✅ 成功读取 %d 条历史记录\n", len(records))
			// 显示前5条和最后5条记录
			for i := 0; i < 5 && i < len(records); i++ {
				record := records[i]
				fmt.Printf("      记录 %d: %s, 电量:%d%%, 时间:%s\n",
					i+1, record.GetPressureString(), record.BatteryLevel, record.GetTimeString())
			}
			if len(records) > 10 {
				fmt.Printf("      ... (省略 %d 条记录) ...\n", len(records)-10)
			}
			for i := len(records) - 5; i < len(records) && i >= 5; i++ {
				record := records[i]
				fmt.Printf("      记录 %d: %s, 电量:%d%%, 时间:%s\n",
					i+1, record.GetPressureString(), record.BatteryLevel, record.GetTimeString())
			}
		}
	}

	// 4. 修改变送器参数
	fmt.Println("\n4. 修改变送器参数 (功能码 0x52):")
	fmt.Println("   设置压力单位为 MPa:")
	err = client.GatewayWriteSubDevParam(5, modbus.SubDevParamPressureUnit, modbus.PressureUnitMPa)
	if err != nil {
		fmt.Printf("   ❌ 错误: %v\n", err)
	} else {
		fmt.Printf("   ✅ 成功设置压力单位为 MPa\n")
	}

	fmt.Println("   设置数据上报间隔为 120秒:")
	err = client.GatewayWriteSubDevParam(5, modbus.SubDevParamDataReportInterval, 120)
	if err != nil {
		fmt.Printf("   ❌ 错误: %v\n", err)
	} else {
		fmt.Printf("   ✅ 成功设置数据上报间隔为 120秒\n")
	}

	// 5. 修改网关参数
	fmt.Println("\n5. 修改网关参数 (功能码 0x53):")
	fmt.Println("   设置 RS485 波特率为 115200:")
	err = client.GatewayWriteGatewayParam(65, modbus.GatewayParamRS485Baudrate, 115200)
	if err != nil {
		fmt.Printf("   ❌ 错误: %v\n", err)
	} else {
		fmt.Printf("   ✅ 成功设置 RS485 波特率为 115200\n")
	}

	fmt.Println("   更新网关系统时间:")
	currentTime := uint32(time.Now().Unix())
	err = client.GatewayWriteGatewayParam(65, modbus.GatewayParamTime, currentTime)
	if err != nil {
		fmt.Printf("   ❌ 错误: %v\n", err)
	} else {
		fmt.Printf("   ✅ 成功更新系统时间为: %s\n",
			time.Unix(int64(currentTime), 0).Format("2006-01-02 15:04:05"))
	}

	// 6. 验证参数修改效果 - 重新读取当前数据
	fmt.Println("\n6. 验证参数修改效果:")
	currentData, err = client.GatewayReadCurrentData(5)
	if err != nil {
		fmt.Printf("   ❌ 错误: %v\n", err)
	} else {
		fmt.Printf("   ✅ 当前压力单位已更新: %s\n", currentData.GetPressureString())
	}

	fmt.Println("\n=== 网关协议功能演示完成 ===")
}
